#!/usr/bin/env python
# -*- encoding=utf8 -*-
#from sqlalchemy.orm import raiseload

from CommonLib import *
from database.models.Controller import Controller
from database.models.ControllerPoint import ControllerPoint
from database.models.DatabaseCommon import *
from database.models.Normal import Normal
from database.models.OperationSet import OperationSet


class WorkManager(threading.Thread):
    def __init__(self, iid):
        self.id = iid
        super(WorkManager, self).__init__()
        self.WorkingThread_args = None
        global_status.ai_ele_global_status.Ins2NormalMap(str(iid), self)

    def __del__(self):
        global_status.ai_ele_global_status.Del4NormalMap(str(self.id))

    def WorkingThread(self, d):
        stepID = d
        s = make_new_engine_new_session()
        opts = s.query(OperationSet).filter_by(NormalID=stepID).all()
        if len(opts) < 1:
            logging.debug('operations len is ', len(opts))
            return json.encoder({'Code': 1, 'desc': u'未找到对应动作'})
        else:
            for i in range(0, len(opts)):
                time.sleep(1.0 / 5)
                if not self.is_alive():
                    logging.warn("work is not active")
                    return
                if opts[i].OptTypeID is None:
                    logging.warn("opt type is not available")
                    continue
                else:
                    opt = opts[i].OptTypeID
                if opts[i].PointID is None:
                    logging.warn('point is not available')
                    continue
                else:
                    point_id = opts[i].PointID
                nowstat = s.query(ControllerPoint, Controller).with_for_update(read=False, nowait=False).filter(
                    ControllerPoint.ControllerID == Controller.id).filter(ControllerPoint.id == point_id).all()
                if len(nowstat) != 1:
                    return json.dumps({"Code": 1, 'desc': u'内部执行条件不满足'})
                cur_value = nowstat[0].Controller.Value
                pointIndex = nowstat[0].ControllerPoint.PointIndex
                hard_id = int(nowstat[0].Controller.HardID)
                controllerID = int(nowstat[0].Controller.id)
                optParams = opts[i].Params
                if opt == 4:
                    t = threading.Thread(target=self.WorkingThread, args=(optParams,))
                    t.start()
                    t.join()
                if opt == 3:
                    # 延时
                    dly = opts[i].Params
                    logging.debug('delay:%s s' % dly)
                    time.sleep(1.0 * int(dly) / 1000)
                if opt is 2:
                    # 关闭一个灯
                    cl = int(cur_value) & 0xff
                    ch = int(cur_value) & 0xff00
                    ch = ch >> 8
                    # 通过point index 组装 发送数据
                    l = 0
                    h = 0
                    oneN = 1
                    if int(pointIndex) > 8:
                        h = oneN << (int(pointIndex) - 8 - 1)
                    else:
                        l = oneN << int(pointIndex - 1)
                    h = ~h & ch
                    l = ~l & cl
                    # 写会数据库下次使用
                    currentValue = (h << 8 | l) & 0xffff
                    controller = s.query(Controller).filter_by(id=controllerID).all()
                    controller[0].Value = str(currentValue)
                    s.commit()
                    hard_id_high = (hard_id >> (8 * 1)) & 0xff
                    hard_id_low = (hard_id >> (8 * 0)) & 0xff
                    send2board = [hard_id_low, hard_id_high, l, h, 111, 6, 1, 2, 0, 0]
                    sendWrap = SendWrap(device_listen_addr)
                    sendWrap.SendData(send2board)
                if opt is 1:
                    # 打开一个灯
                    cl = int(cur_value) & 0xff
                    ch = int(cur_value) & 0xff00
                    ch = ch >> 8
                    # 通过point index 组装 发送数据
                    l = 0
                    h = 0
                    oneN = 1
                    if int(pointIndex) > 8:
                        h = oneN << (int(pointIndex) - 8 - 1)
                    else:
                        l = oneN << int(pointIndex - 1)
                    # 通过opt组合发送的数据
                    l = l | cl
                    h = h | ch
                    # 写会数据库下次使用
                    currentValue = (h << 8 | l) & 0xffff
                    controller = s.query(Controller).filter_by(id=controllerID).one()
                    controller.Value = str(currentValue)
                    s.commit()
                    hard_id_high = (hard_id >> (8 * 1)) & 0xff
                    hard_id_low = (hard_id >> (8 * 0)) & 0xff
                    send2board = [hard_id_low, hard_id_high, l, h, 0, 0, 0, 0, 0, 0]
                    sendWrap = SendWrap(device_listen_addr)
                    sendWrap.SendData(send2board)
        # s.close()
        logging.info('session closed')

    def CheckError(self):
        s = make_new_engine_new_session()
        no = s.query(Normal, OperationSet).filter(Normal.id == OperationSet.NormalID).filter(
            Normal.id == self.id).order_by(OperationSet.id).all()
        ret = {'code': 0,
               'desc': 'success'}
        if len(no) is 0:
            ret['code'] = 1
            ret['desc'] = 'start work id error: do not find any data'
        return ret

    def stop(self):
        self.stop()
        # threading.Thread._Thread__stop(self)

    def run(self):
        logging.debug('start thread')
        self.WorkingThread(self.WorkingThread_args)
        global_status.ai_ele_global_status.Del4NormalMap(str(self.id))

    def Start(self):
        self.WorkingThread_args = self.id
        super(WorkManager, self).start()
